﻿///////////////////////////////////////////////////////////////////////////////
// 文件名： Scene.cc
// 作者：   671643387@qq.com
// 日期：   2015年11月1日 下午6:39:28
// 简介：   
///////////////////////////////////////////////////////////////////////////////

#include <cassert>

#include "graphics/graphics/render/Render.hpp"
#include "graphics/graphics/Scene.hpp"
using namespace ::graphics::graphics;

Scene::Scene()
    : render_(NULL)
    , cameras_()
    , graphicsNodes_()
{

}

Scene::~Scene()
{

}

///////////////////////////////////////////////////////////////////////////////

void Scene::SetRender(::graphics::graphics::render::Render* render)
{
    render_ = render;
}

::graphics::graphics::render::Render* Scene::GetRender() const
{
    return render_;
}

void Scene::RenderFrame()
{
    assert(render_ != NULL);
    if (cameras_.empty())
        return;

    CameraArray::iterator it = cameras_.begin();
    CameraArray::iterator end = cameras_.end();
    for(; it != end; ++it)
    {
        if((*it)->BeginFrame())
        {
            RenderGraphicsNodes_((*it));
            (*it)->EndFrame();
        }
    }
}

void Scene::AddCamera(::graphics::graphics::scenenode::CameraPtr camera)
{
    assert(camera);
    camera->SetScene(this);
    if (cameras_.empty())
    {
        cameras_.insert(cameras_.begin(), camera);
    }
    else
    {
        CameraArray::iterator it = cameras_.begin();
        CameraArray::iterator end = cameras_.end();
        for(; it != end; ++it)
        {
            if ((*it)->GetIndex() > camera->GetIndex())
                break;
        }
        cameras_.insert(it, camera);
    }
}

void Scene::RemoveCamera(int id)
{
    CameraArray::iterator it = cameras_.begin();
    CameraArray::iterator end = cameras_.end();
    for(; it != end; ++it)
    {
        if ((*it)->GetID() == id)
            break;
    }
    if (it != end)
    {
        (*it)->SetScene(NULL);
        cameras_.erase(it);
    }
}

::graphics::graphics::scenenode::CameraPtr Scene::GetCamera(int id)
{
    CameraArray::iterator it = cameras_.begin();
    CameraArray::iterator end = cameras_.end();
    for(; it != end; ++it)
    {
        if ((*it)->GetID() == id)
            break;
    }
    if (it != end)
        return *it;
    return ::graphics::graphics::scenenode::CameraPtr();
}

void Scene::AddGraphicsNode(::graphics::graphics::scenenode::GraphicsNodePtr node)
{
    assert(node);
    node->SetScene(this);
    graphicsNodes_.insert(graphicsNodes_.end(), node);
}

void Scene::RemoveGraphicsNode(::graphics::graphics::scenenode::GraphicsNode* node)
{
    GraphicsNodeArray::iterator it = graphicsNodes_.begin();
    GraphicsNodeArray::iterator end = graphicsNodes_.end();
    for(; it != end; ++it)
    {
        if (it->get() == node)
            break;
    }
    if (it != end)
        graphicsNodes_.erase(it);
}

///////////////////////////////////////////////////////////////////////////////

void Scene::RenderGraphicsNodes_(::graphics::graphics::scenenode::CameraPtr& camera)
{
    GraphicsNodeArray::iterator it = graphicsNodes_.begin();
    GraphicsNodeArray::iterator end = graphicsNodes_.end();
    for(; it != end; ++it)
    {
        // TODO: CAMERA CHECK
        (*it)->Render();
    }
}